using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.ComponentModel;
using System.Reflection;
using System.Xml.Serialization;
using System.Globalization;

namespace Umdf.SideShow.Scf.ObjectModel
{
    public abstract class ScfObject : SideShowObject
    {
        protected internal virtual void DeserializeFromXml(XmlNode node)
        {
        }

        protected T GetAttribute<T>(XmlNode node, string name)
        {
            return GetAttribute<T>(node, name, default(T));
        }

        protected T GetAttribute<T>(XmlNode node, string name, T def)
        {
            XmlAttribute attr = node.Attributes[name];
            if (attr == null)
            {
                return def;
            }
            else
            {
                Type t = typeof(T);
                if (t == typeof(string))
                {
                    return (T)(object) attr.Value;
                }
                else if (t == typeof(uint))
                {
                    return (T)(object)XmlConvert.ToUInt32(attr.Value);
                }
                else if (t == typeof(int))
                {
                    return (T)(object)XmlConvert.ToInt32(attr.Value);
                }
                else if (t == typeof(byte))
                {
                    return (T)(object)XmlConvert.ToByte(attr.Value);
                }
                else if (t == typeof(bool))
                {
                    return (T)(object)XmlConvert.ToBoolean(attr.Value);
                }
                else if (t == typeof(char))
                {
                    return (T)(object)XmlConvert.ToChar(attr.Value);
                }
                else if (t == typeof(DateTime))
                {
                    return (T)(object)XmlConvert.ToDateTime(attr.Value, XmlDateTimeSerializationMode.Local);
                }
                else if (t == typeof(decimal))
                {
                    return (T)(object)XmlConvert.ToDecimal(attr.Value);
                }
                else if (t == typeof(double))
                {
                    return (T)(object)XmlConvert.ToDouble(attr.Value);
                }
                else if (t == typeof(Guid))
                {
                    return (T)(object)XmlConvert.ToGuid(attr.Value);
                }
                else if (t == typeof(short))
                {
                    return (T)(object)XmlConvert.ToInt16(attr.Value);
                }
                else if(t == typeof(long))
                {
                    return (T)(object)XmlConvert.ToInt64(attr.Value);
                }
                else if (t == typeof(sbyte))
                {
                    return (T)(object)XmlConvert.ToSByte(attr.Value);
                }
                else if (t == typeof(float))
                {
                    return (T)(object)XmlConvert.ToSingle(attr.Value);
                }
                else if (t == typeof(TimeSpan))
                {
                    return (T)(object)XmlConvert.ToTimeSpan(attr.Value);
                }
                else if (t == typeof(ushort))
                {
                    return (T)(object)XmlConvert.ToUInt16(attr.Value);
                }
                else if (t == typeof(ulong))
                {
                    return (T)(object)XmlConvert.ToUInt64(attr.Value);
                }
                else if (t.IsEnum)
                {
                    foreach (FieldInfo fi in t.GetFields())
                    {
                        if (fi.IsDefined(typeof(XmlEnumAttribute), false))
                        {
                            XmlEnumAttribute a = (XmlEnumAttribute)fi.GetCustomAttributes(typeof(XmlEnumAttribute), false)[0];
                            if (a.Name == attr.Value)
                            {
                                return (T) Enum.Parse(t, fi.Name, true);
                            }
                        }
                    }
                    return (T)Enum.Parse(t, attr.Value, true);
                }
                else
                {
#if PocketPC
                    return (T) Convert.ChangeType(attr.Value, t, CultureInfo.InvariantCulture);
#else
                    TypeConverter c = TypeDescriptor.GetConverter(t);
                    if (c.CanConvertFrom(typeof(string)))
                    {
                        return (T)c.ConvertFromInvariantString(attr.Value);
                    }
                    else
                    {
                        return def;
                    }
#endif
                }

            }
        }
    }
}
